package com.onec.service.design;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 单例 饿汉模式
 */
public class Singleton {

  // 私有
  private Singleton() {
  }

  private static final Singleton SINGLETON = new Singleton();

  public static Singleton getInstance() {
    return SINGLETON;
  }
}

// 懒汉 模式单例
class Singleton2 {

  static Singleton2 singleton2;

  private Singleton2() {
  }

  static Singleton2 getInstance() {
    if (singleton2 == null) {
      singleton2 = new Singleton2();
    }
    return singleton2;
  }
}


// 懒汉内置锁
class BSingleton {

  static BSingleton bSingleton;

  private BSingleton() {
  }

  static synchronized BSingleton getInstance() {
    if (bSingleton == null) {
      bSingleton = new BSingleton();
    }
    return bSingleton;
  }
}


// 双重检查 锁单例
class ESingleton {

  private ESingleton() {
  }

  static ESingleton eSingleton;

  static ESingleton getInstance() {
    if (eSingleton == null) {
      synchronized (ESingleton.class) {
        if (eSingleton == null) {
          eSingleton = new ESingleton();
        }
      }
    }
    return eSingleton;
  }
}

// 禁止指令重排的懒汉 单例
class ASingleton {

  private ASingleton() {
  }

  volatile static ASingleton singleton;

  static ASingleton getInstance() {
    if (singleton == null) {
      synchronized (ASingleton.class) {
        if (singleton == null) {
          singleton = new ASingleton();
        }
      }
    }
    return singleton;
  }
}

/**
 * 静态内部类 懒加载 ：重点推荐 单例方式！
 */
class RSingleton {

  private RSingleton() {
  }

  private static class LazyHolder {

    private static final RSingleton R_SINGLETON = new RSingleton();
  }

  static final RSingleton getInstance() {
    return LazyHolder.R_SINGLETON;
  }
}

/**
 * 枚举单例
 */
enum FSingleton {
  INSTANCE;

  public FSingleton getInstance() {
    return INSTANCE;
  }
}

// 自旋 安全获取单例
class ZSingleton {
    private static final AtomicReference<ZSingleton> atomicReference = new AtomicReference<>();
    private ZSingleton singleton;
    public ZSingleton() {
    }
    public static final ZSingleton getZSingleton() {
        for (; ; ) {
            ZSingleton zSingleton = atomicReference.get();
            if (zSingleton != null) {
                return zSingleton;
            }
            atomicReference.compareAndSet(null, new ZSingleton());
            return atomicReference.get();
        }
    }
}
